﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HAC
{
    public class Cluster : IEnumerable
    {
        HashSet<Element> elements = new HashSet<Element>();
        Fusion fusion;

        public int id;

        private float avg_distance = -1;//average distance between element pairs

        public float Avg_distance
        {
            get 
            {
                if (avg_distance < 0)
                {
                    int count = 0;
                    float sum = 0;
                    foreach (float d in distances)
                    {
                        sum += d; count++;
                    }
                    if(count==0)
                    {
                        avg_distance = 1;//1 indicates max distances
                    }else
                    {
                        avg_distance = sum / count;
                    }
                }
                return avg_distance;
            }
        }
        private float max_distance = -1;//maximum distance between element pairs

        public float Max_distance
        {
            get 
            {
                if (max_distance < 0)
                {
                    foreach (float d in distances)
                    {
                        if (d > max_distance)
                        {
                            max_distance = d;
                        }
                    }
                }
                if (max_distance < 0)
                {
                    max_distance = 1;
                }
                return max_distance; 
            }
        }
        private float min_distance = -1;//minimum distance between element pairs

        public float Min_distance
        {
            get 
            {
                if (min_distance < 0)
                {
                    min_distance = 1;
                    foreach (float d in distances)
                    {
                        if (d < min_distance)
                        {
                            min_distance = d;
                        }
                    }
                }
                return min_distance; 
            }
        }
        private List<float> distances = new List<float>();

        public List<float> Distances
        {
            get { return distances; }
        }

        public void AddDistance(float newdistance)
        {
            distances.Add(newdistance);
        }
        public void AddDistances(List<float> newdistances)
        {
            distances.AddRange(newdistances);
        }

        public Cluster(Fusion fusion)
        {
            this.fusion = fusion;
            this.id = HAC.ClusterCountAccumulator++;
        }
        public int elementNumber()
        {
            return elements.Count;
        }
        internal void AddElement(Element element)
        {
            this.elements.Add(element);
        }

        internal void AddElements(Element[] elements)
        {
            foreach (Element e in elements)
                this.elements.Add(e);
        }

        internal Element[] GetElements()
        {
            return elements.ToArray<Element>();
        }

        internal float CalculateDistance(Cluster otherCluster)
        {
            return fusion.CalculateDistance(this, otherCluster);
        }

        #region IEnumerable Member

        public IEnumerator GetEnumerator()
        {
            return elements.GetEnumerator();
        }

        #endregion
    }
}
